home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / nextrad.lha / NeXtRad / engine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-25  |  24.2 KB  |  874 lines

  1. /* engine.c */
  2.  
  3. /* written by : Jason R. Wilson    2/21/93 */
  4.  
  5. /* provides user interface with access to radiosity engine */
  6.  
  7. #import <math.h>
  8. #include <stdio.h>
  9. #include "datastruct.h"
  10. #include "vector-matrix.h"
  11. #include "clip.h"
  12. #include "misc.h"
  13. #include "objIO.h"
  14. #include "render.h"
  15. #include "hemicube.h"
  16. #include "wireframe.h"
  17. #include "mesh.h"
  18. #include "NeXtInterface.h"
  19.  
  20. #define PI 3.141592654
  21. #define GaussTol 0.0001 /* gives a .01% tolerence for Gauss-Siedel */
  22. double **FFMatrix; /* don't forget to offset by 1!!! */
  23. double **Zbuffer; 
  24. Color **ScreenMap;
  25. Matrix Composition;
  26. Point  VRP;
  27. Vector VPN,Up,u,v,n;
  28. Window ViewWindow;
  29. double  Eye;
  30. double dotprod;
  31. Vector upp;
  32. int NumPolys;
  33. int NumVerts;
  34. int adaptive;
  35. double MoveFactor = 0.1; /* the amount to add on to vectors when moving */
  36. double TurnFactor = 1.0; /* the angle of the turn */
  37.  
  38. double MaxIntensity;
  39.  
  40.  
  41.  
  42. /*----------------------------------------------------------------------*/
  43. void ReadScene (char *SceneFileName)
  44. {
  45.  
  46. /* reads in a .scene file */
  47.   
  48.    FILE *fp; /* This is the file pointer for the scene file */ 
  49.    char ObjectFileName[256];
  50.    unsigned int TransformType;
  51.    Matrix Copy,New,NewIn,CopyIn;
  52.    double scaleX,scaleY,scaleZ;
  53.    double transX,transY,transZ;
  54.    ObjectCell *Object;
  55.    int NumObjects;
  56.    int loop;
  57.    double c,s;
  58.    int rotationType;
  59.    double rotationAngle;
  60.    double adaptivetol;
  61.    int shouldadapt;
  62.    
  63.    
  64.    ObjectHead = NULL;
  65.  
  66.    printf ("Welcome to NeXtRad!\n");
  67.    printf ("Please enter the name of the scene that you wish to view:\n");
  68.    scanf ("%s",SceneFileName);
  69.    fp = fopen(SceneFileName,"r"); /* open data file */
  70.  
  71.    fscanf (fp,"%lf %lf %lf",&VRP.x,&VRP.y,&VRP.z); /* read in VRP */
  72.    fscanf (fp,"%lf %lf %lf",&VPN.dx,&VPN.dy,&VPN.dz); /* read in VPN */
  73.    fscanf (fp,"%lf %lf %lf",&Up.dx,&Up.dy,&Up.dz); /* read in up vector */
  74.    fscanf (fp,"%lf %lf %lf %lf",&ViewWindow.Wl,&ViewWindow.Wr,
  75.                         &ViewWindow.Wb,&ViewWindow.Wt); /* Viewwindow */
  76.    fscanf (fp,"%lf",&Eye); /* eye */
  77.    fscanf (fp,"%d",&adaptive); /* number of times to adaptively subdivide the mesh */
  78.    fscanf  (fp,"%lf",&adaptivetol); /* read in the tolerence for adaptive subdivision */
  79.  
  80.    initAdaptiveTol (adaptivetol); /* init. value in the mesh package */
  81.    
  82.    /* Compute u,v,n */
  83.  
  84.    n = Normalize (VPN);
  85.    dotprod = Dotprod (Up,n);
  86.    upp.dx = Up.dx - dotprod*n.dx;
  87.    upp.dy = Up.dy - dotprod*n.dy;
  88.    upp.dz = Up.dz - dotprod*n.dz;
  89.    v = Normalize (upp);
  90.    u = Cross (n,v);
  91.    
  92.    ProduceTransform (VRP,u,v,n,Eye,&Composition);
  93.    
  94.    fscanf (fp,"%d",&NumObjects); /* get the number of objects */
  95.    
  96.  
  97.    for (loop = 0;loop < NumObjects;loop++)
  98.    {
  99.       fscanf (fp,"%s",ObjectFileName); /* get object file name */
  100.       Object = (ObjectCell *)(malloc(sizeof(ObjectCell)));
  101.       InitObjectCell (Object);
  102.       fscanf (fp,"%d",&shouldadapt); /* should this object be adaptively subdivided */
  103.       if (shouldadapt == 0)
  104.     Object->ShouldAdapt = false;
  105.       else
  106.     Object->ShouldAdapt = true;
  107.       ReadInObject (Object,ObjectFileName);
  108.       createIdentity (4,Object->Transform.mat);
  109.       createIdentity (4,Object->InverseTransform.mat);
  110.       
  111.       /* read in subdivision factor */
  112.       fscanf (fp,"%d",&Object->SubFactor);
  113.  
  114.       fscanf (fp,"%u",&TransformType); /* what kind of transform  */
  115.       
  116.       while (!(TransformType == 0))
  117.       {
  118.      createIdentity (4,New.mat);
  119.      createIdentity (4,NewIn.mat);
  120.      
  121.      switch (TransformType) {
  122.      case 1: /* rotation */
  123.        fscanf (fp,"%d %lf",&rotationType,&rotationAngle);
  124.        c = cos(rotationAngle*PI/180.0);
  125.        s = sin(rotationAngle*PI/180.0);              
  126.        switch (rotationType) {
  127.        case 1: /* rotation about x-axis */
  128.          New.mat[5] = c;
  129.          New.mat[6] = s;
  130.          New.mat[9] = (-1.0)*s;
  131.          New.mat[10] = c;
  132.          Transpose (&New,&NewIn);
  133.          break;
  134.        case 2: /* rotation about y-axis */
  135.          New.mat[0] = c;
  136.          New.mat[2] = (-1.0)*s;
  137.          New.mat[8] = s;
  138.          New.mat[10] = c;
  139.          Transpose (&New,&NewIn);
  140.          break;
  141.        case 3: /* rotation about z-axis */
  142.          New.mat[0] = c;
  143.          New.mat[1] = s;
  144.          New.mat[4] = (-1.0)*s;
  145.          New.mat[5] = c;
  146.          Transpose (&New,&NewIn);
  147.          break; }
  148.        break;
  149.      case 2: /* scale */
  150.        fscanf (fp,"%lf %lf %lf",&scaleX,&scaleY,&scaleZ);
  151.        New.mat[0] = scaleX;
  152.        New.mat[5] = scaleY;
  153.        New.mat[10] = scaleZ;
  154.        NewIn.mat[0] = 1.0/scaleX;
  155.        NewIn.mat[5] = 1.0/scaleY;
  156.        NewIn.mat[10] = 1.0/scaleZ;
  157.        break;
  158.      case 3: /* translate */
  159.        fscanf (fp,"%lf %lf %lf",&transX,&transY,&transZ);
  160.        New.mat[12] = transX;
  161.        New.mat[13] = transY;
  162.        New.mat[14] = transZ;
  163.        NewIn.mat[12] = (-1.0)*transX;
  164.        NewIn.mat[13] = (-1.0)*transY;
  165.        NewIn.mat[14] = (-1.0)*transZ;
  166.        break;
  167.      }
  168.      
  169.      matrixCopy (Object->Transform.mat,Copy.mat); 
  170.      matrixMultiply (4,Copy.mat,New.mat,Object->Transform.mat);
  171.  
  172.      matrixCopy (Object->InverseTransform.mat,CopyIn.mat);
  173.      matrixMultiply (4,NewIn.mat,CopyIn.mat,Object->InverseTransform.mat);
  174.      
  175.      fscanf (fp,"%u",&TransformType); /* what kind of transform  */
  176.       }
  177.  
  178.       
  179.       /* insert object into object list */
  180.  
  181.  
  182.       if (ObjectHead == NULL)
  183.       {
  184.      ObjectHead = Object;
  185.      Object->Next = NULL;
  186.       }
  187.       else
  188.       {
  189.      Object->Next = ObjectHead;
  190.      ObjectHead = Object;
  191.       }
  192.  
  193.    }
  194.  
  195.    close (fp);
  196.  
  197. }
  198.  
  199.  
  200. /***********************************************************************/
  201.  
  202. void SetUpVectors (ObjectCell *ObjectHead,Color *BVec,Color *EVec,
  203.            Color *RVec,int NumPolys)
  204.  
  205. {
  206.    ObjectCell *Object;
  207.    PolygonCell *Poly;
  208.    int loop;
  209.  
  210.    
  211.    /* set up the initial vectors */
  212.  
  213.    Object = ObjectHead;
  214.    Poly = Object->PolygonHead;
  215.  
  216.    for (loop = 0;loop < NumPolys;loop++)
  217.    {
  218.       EVec[loop].r = Poly->E.r;
  219.       EVec[loop].g = Poly->E.g;
  220.       EVec[loop].b = Poly->E.b;
  221.  
  222.       RVec[loop].r = Poly->R.r;
  223.       RVec[loop].g = Poly->R.g;
  224.       RVec[loop].b = Poly->R.b;
  225.  
  226.       BVec[loop].r = EVec[loop].r;
  227.       BVec[loop].g = EVec[loop].g;
  228.       BVec[loop].b = EVec[loop].b;
  229.  
  230.       if ((Poly->Next == NULL) && (!(Object->Next == NULL)))
  231.      {
  232.         Object = Object->Next;
  233.         Poly = Object->PolygonHead;
  234.      }
  235.       else 
  236.      Poly = Poly->Next;         
  237.    }
  238.  
  239. }
  240.    
  241.    
  242. /*----------------------------------------------------------------------*/
  243.  
  244.  
  245. void ComputeRadiosityIntensities (ObjectCell *ObjectHead,int NumPolys)
  246.  
  247. /* Computes the intensities at each vertex using radiosity */
  248.  
  249. {
  250.    Color BVec[NumPolys]; 
  251.    Color EVec[NumPolys];
  252.    Color RVec[NumPolys];
  253.    Color Old[NumPolys]; /* used to measure change */
  254.    ObjectCell *Object;
  255.    PolygonCell *Poly;
  256.    int loop,loop2,loop3;
  257.    int count;
  258.    VertexCell *CurrentVert;
  259.    PolygonListCell *CurrentListPoly;
  260.    Boolean GoOn; /* should Gauss-Siedel continue? */ 
  261.  
  262.    /* get memory for form-factor matrix */
  263.    
  264.    FFMatrix = (double **)(malloc(NumPolys*sizeof(double *)));
  265.    for (loop = 0;loop < NumPolys;loop++)
  266.       FFMatrix[loop] = (double *)(malloc(NumPolys*sizeof(double)));
  267.  
  268.  
  269.    /* init. the form-factor matrix */
  270.    for (loop = 0;loop < NumPolys;loop++)
  271.       for (loop2 = 0;loop2 < NumPolys;loop2++)
  272.         FFMatrix[loop][loop2] = 0.0;
  273.  
  274.    SetUpVectors (ObjectHead,BVec,EVec,RVec,NumPolys); /* init. the vectors */
  275.  
  276.    /* compute the form-factors */
  277.  
  278.    Object = ObjectHead;   
  279.    Poly = ObjectHead->PolygonHead;
  280.  
  281.  
  282.    for (loop = 0;loop < NumPolys;loop++) 
  283.    {
  284.      printf ("projecting onto patch %d\n",loop + 1);
  285.      
  286.      ProjectPatch(Poly,FFMatrix[loop]); /* compute the row of form-factors for patch */
  287.      
  288.      /* advance the poly pointer */
  289.      
  290.      if ((Poly->Next == NULL) && (!(Object->Next == NULL)))
  291.        {
  292.      Object = Object->Next;
  293.      Poly = Object->PolygonHead;
  294.        }
  295.      else 
  296.        Poly = Poly->Next;               
  297.    }
  298.    
  299.    /* let's see the results ! */
  300.  
  301. /*
  302.    for (loop = 0;loop < NumPolys;loop++)
  303.       for (loop2 = 0;loop2 < NumPolys;loop2++)
  304.      printf ("the %d,%d form-factor is %lf\n",loop,loop2,
  305.          FFMatrix[loop][loop2]); 
  306. */
  307.  
  308.    /* iteratively solve for the radiosities (to given tol.) */
  309.  
  310.    printf ("solving matrix ... \n");
  311.    loop3 = 0; /* count the number of iterations required */
  312.    GoOn = true;
  313.    while (GoOn == true)
  314.      {
  315.      GoOn = false; /* assume done */
  316.      loop3++; /* another iteration */
  317.      for (loop = 0;loop < NumPolys;loop++)
  318.        {
  319.      Old[loop].r = BVec[loop].r;
  320.      Old[loop].g = BVec[loop].g;
  321.      Old[loop].b = BVec[loop].b;
  322.        }
  323.      for (loop = 0;loop < NumPolys;loop++)
  324.        {
  325.      BVec[loop].r = EVec[loop].r;
  326.      for (loop2 = 0;loop2 < NumPolys;loop2++)
  327.        if (!(loop2 == loop))
  328.            BVec[loop].r += RVec[loop].r*
  329.            BVec[loop2].r*FFMatrix[loop][loop2];
  330.      BVec[loop].g = EVec[loop].g;
  331.      for (loop2 = 0;loop2 < NumPolys;loop2++)
  332.        if (!(loop2 == loop))
  333.          {
  334.            BVec[loop].g += RVec[loop].g*
  335.          BVec[loop2].g*FFMatrix[loop][loop2];
  336.          }
  337.      BVec[loop].b = EVec[loop].b;
  338.      for (loop2 = 0;loop2 < NumPolys;loop2++)
  339.        if (!(loop2 == loop))
  340.          {
  341.            BVec[loop].b += RVec[loop].b*
  342.          BVec[loop2].b*FFMatrix[loop][loop2];
  343.          }
  344.        }
  345.      /* next, test to see if another iteration is required */
  346.      for (loop = 0;loop < NumPolys;loop++)
  347.        {
  348.      if ((((Old[loop].r - BVec[loop].r)/Old[loop].r) > GaussTol) ||
  349.          (((Old[loop].r - BVec[loop].r)/BVec[loop].r) < (-1.0*GaussTol)))
  350.        GoOn = true;
  351.      if ((((Old[loop].g - BVec[loop].g)/Old[loop].g) > GaussTol) ||
  352.          (((Old[loop].g - BVec[loop].g)/BVec[loop].g) < (-1.0*GaussTol)))
  353.        GoOn = true;
  354.      if ((((Old[loop].b - BVec[loop].b)/Old[loop].b) > GaussTol) ||
  355.          (((Old[loop].b - BVec[loop].b)/BVec[loop].b) < (-1.0*GaussTol)))
  356.        GoOn = true;     
  357.        }
  358.      
  359.    }
  360.  
  361.    printf ("It took %d iterations\n",loop3);
  362.  
  363.    Object = ObjectHead;   
  364.    Poly = ObjectHead->PolygonHead;
  365.  
  366.    for (loop = 0;loop < NumPolys;loop++) 
  367.    {
  368.  
  369.      Poly->B.r = BVec[loop].r;
  370.      Poly->B.g = BVec[loop].g;
  371.      Poly->B.b = BVec[loop].b;     
  372.      
  373.      /* advance the poly pointer */
  374.      
  375.      if ((Poly->Next == NULL) && (!(Object->Next == NULL)))
  376.        {
  377.      Object = Object->Next;
  378.      Poly = Object->PolygonHead;
  379.        }
  380.      else 
  381.        Poly = Poly->Next;               
  382.    }
  383.    
  384.    /* move radiosities from patches to vertices */
  385.  
  386.  
  387.    Object = ObjectHead;
  388.    
  389.    while (!(Object == NULL))
  390.    {
  391.       CurrentVert = Object->VertexHead;
  392.       while (!(CurrentVert == NULL))
  393.       {
  394.      CurrentVert->B.r = 0.0;
  395.      CurrentVert->B.g = 0.0;
  396.      CurrentVert->B.b = 0.0;
  397.      count = 0;
  398.      CurrentListPoly = CurrentVert->Polygons;
  399.      while (!(CurrentListPoly == NULL))
  400.      {
  401.         count++;
  402.         CurrentVert->B.r += BVec[(CurrentListPoly->Polygon->ID - 1)].r;
  403.         CurrentVert->B.g += BVec[(CurrentListPoly->Polygon->ID - 1)].g;
  404.         CurrentVert->B.b += BVec[(CurrentListPoly->Polygon->ID - 1)].b;
  405.         CurrentListPoly = CurrentListPoly->Rest;
  406.      }
  407.      CurrentVert->B.r /= (double)count;
  408.      CurrentVert->B.g /= (double)count;
  409.      CurrentVert->B.b /= (double)count;
  410.      
  411.  
  412.      CurrentVert = CurrentVert->Next;
  413.       }
  414.       Object = Object->Next;
  415.    }
  416.  
  417.    /* free memory for form-factor matrix */
  418.    
  419.    for (loop = 0;loop < NumPolys;loop++)
  420.       free (FFMatrix[loop]);
  421.    free (FFMatrix);
  422.  
  423.  
  424.  
  425. }
  426.  
  427.  
  428. /***********************************************************************/
  429.  
  430. void ReadWorld (void)
  431.      /* reads prestored patch and vertex radiosities from a file */
  432. {
  433.   char filename[256];
  434.   FILE *fp;
  435.   ObjectCell *Object;
  436.   VertexCell *Vertex;
  437.   PolygonCell *Polygon;
  438.   
  439.   printf ("Please enter the name of file that contains the patch and vertex radiosities :\n");
  440.   scanf ("%s",filename);
  441.   printf ("Thank you. Reading ... \n");
  442.   fp = fopen (filename,"r");
  443.   Object = ObjectHead;
  444.   while (!(Object == NULL))
  445.     {
  446.       Vertex = Object->VertexHead;
  447.       while (!(Vertex == NULL))
  448.     {
  449.       fscanf (fp,"%lf %lf %lf",&Vertex->B.r,&Vertex->B.g,&Vertex->B.b);
  450.       Vertex = Vertex->Next;
  451.     }
  452.       Polygon = Object->PolygonHead;
  453.       while (!(Polygon == NULL))
  454.     {
  455.       fscanf (fp,"%lf %lf %lf",&Polygon->B.r,&Polygon->B.g,&Polygon->B.b);
  456.       Polygon = Polygon->Next;
  457.     }
  458.       Object = Object->Next;
  459.     }
  460.   close(fp); /* close the file */
  461.   printf ("Done reading file\n");
  462.  
  463. }
  464.  
  465. /***********************************************************************/
  466.  
  467. void WriteWorld (void)
  468.      /* writes vertex and patch radiosities to a file for storage */
  469. {
  470.   char filename[256];
  471.   FILE *fp;
  472.   ObjectCell *Object;
  473.   VertexCell *Vertex;
  474.   PolygonCell *Polygon;
  475.   
  476.   printf ("Please enter the name of the output file\n");
  477.   scanf ("%s",filename); 
  478.   printf ("Thank you. Writing ... \n");
  479.   fp = fopen (filename,"w");
  480.   Object = ObjectHead;
  481.   while (!(Object == NULL))
  482.     {
  483.       Vertex = Object->VertexHead;
  484.       while (!(Vertex == NULL))
  485.     {
  486.       fprintf (fp,"%lf %lf %lf\n",Vertex->B.r,Vertex->B.g,Vertex->B.b);
  487.       Vertex = Vertex->Next;
  488.     }
  489.       Polygon = Object->PolygonHead;
  490.       while (!(Polygon == NULL))
  491.     {
  492.       fprintf (fp,"%lf %lf %lf\n",Polygon->B.r,Polygon->B.g,Polygon->B.b);
  493.       Polygon = Polygon->Next;
  494.     }
  495.       Object = Object->Next;
  496.     }
  497.   close(fp); /* close the file */
  498.   printf ("Done writing file\n");
  499.  
  500. }  
  501.      
  502.  
  503. /***********************************************************************/
  504.  
  505. void InitComp(void)
  506. /* get initial mesh, radiosities for the initial mesh, and perform initial 
  507.    adaptive subdivisions.  */
  508.    
  509. {
  510.   int loop,loop2;
  511.   ObjectCell *Object;
  512.  char answer[256];
  513.   
  514.   Object = ObjectHead;
  515.   while (!(Object == NULL))
  516.     {
  517.       TransformObject (Object);
  518.       IdentifyVertices(Object);
  519.       for (loop = 0;loop < (Object->SubFactor - 1);loop++)
  520.     {
  521.       SubDivide (Object,Object->NoofVertices);
  522.       IdentifyVertices(Object);
  523.     }
  524.       ComputeNormals (Object);
  525.       Object = Object->Next;
  526.     }
  527.   
  528.   
  529.   NumPolys = IdentifyPolys (ObjectHead);
  530.   NumVerts = IdentifyVerts (ObjectHead);
  531.   
  532.   printf ("here is numpolys %d\n",NumPolys);
  533.   printf ("here is numverts %d\n",NumVerts);
  534.  
  535.  
  536.   printf ("About to compute patch radiosities!\n");
  537.   printf ("Would you like to load them from a file : (y or n)\n");
  538.   scanf ("%s",answer);
  539.   if ((answer[0] == 'y') || (answer[0] == 'Y'))
  540.     ReadWorld();
  541.   else
  542.     {
  543.       ComputeRadiosityIntensities (ObjectHead,NumPolys); 
  544.       printf ("Patch Radiosities have been computed for this scene!\n");
  545.       printf ("Would you like to write them to a file : (y or n)\n");
  546.       scanf ("%s",answer);
  547.       if ((answer[0] == 'y') || (answer[0] == 'Y')) 
  548.       WriteWorld();
  549.     }
  550.   
  551.   for (loop = 0;loop < adaptive;loop++)
  552.     {
  553.       printf ("subdividing...\n");
  554.       Object = ObjectHead;
  555.       while (!(Object == NULL))
  556.     {
  557.       if (Object->ShouldAdapt == true)
  558.         {
  559.           IdentifyVertices(Object);
  560.           SubdivideObjects(Object,Object->NoofVertices,NumPolys);
  561.         }
  562.           Object = Object->Next;
  563.     }
  564.       
  565.     }
  566.   
  567.   
  568.     
  569. }
  570. /*----------------------------------------------------------------------*/
  571.  
  572. void adapt(void)
  573. /* does an adaptive mesh-generation pass */
  574.  
  575. {
  576.   ObjectCell *Object;
  577.   
  578.   printf ("adaptively subdividing ...\n");
  579.   Object = ObjectHead;
  580.   while (!(Object == NULL))
  581.     {
  582.       if (Object->ShouldAdapt == true)
  583.     {
  584.       IdentifyVertices(Object);
  585.       SubdivideObjects(Object,Object->NoofVertices,NumPolys);
  586.     }
  587.       Object = Object->Next;
  588.     }
  589. }
  590. /*----------------------------------------------------------------------*/
  591. void renderit(void)
  592. {
  593.   /* render the scene */
  594.   
  595.   int loop,loop2;
  596.   ObjectCell *Object;
  597.  
  598.   CullBackFaces (ObjectHead,Eye,VRP,n); /* cull back faces */
  599.   TransformView (ObjectHead,Composition); /* compute view coordinates */
  600.   
  601.   MaxIntensity = -1.0; /* init. max intensity */
  602.   
  603.   /* init. Zbuffer and ScreenMap */
  604.   for (loop = 0;loop < winHeight;loop++)
  605.     for (loop2 = 0;loop2 < winWidth;loop2++)
  606.       {
  607.     Zbuffer[loop2][loop] = 1000.0;  /* ?!?!? */
  608.     ScreenMap[loop2][loop].r = 0.0;
  609.     ScreenMap[loop2][loop].g = 0.0;
  610.     ScreenMap[loop2][loop].b = 0.0;
  611.       }
  612.   
  613.   
  614.   Object = ObjectHead;
  615.  
  616.    while (!(Object == NULL))
  617.    {
  618.       RenderObject (Object,Zbuffer,ScreenMap,ViewWindow,&MaxIntensity,
  619.             winWidth,winHeight,u,v,n,VRP);
  620.       Object = Object->Next;
  621.    }
  622.  
  623.  
  624.    printf ("writing to ScreenBuf ...\n");
  625.  
  626.    for (loop = 0;loop < winHeight;loop++)
  627.       for (loop2 = 0;loop2 < winWidth;loop2++)
  628.     {
  629.       SetPixel (loop2,loop,((unsigned char)(rint(((
  630.              ScreenMap[loop2][loop].r)/MaxIntensity)*255))),
  631.                        ((unsigned char)(rint(((
  632.              ScreenMap[loop2][loop].g)/MaxIntensity)*255))),
  633.                        ((unsigned char)(rint(((
  634.              ScreenMap[loop2][loop].b)/MaxIntensity)*255))));
  635.        }     
  636.    printf ("done\n");
  637.  
  638. }  
  639.  
  640. /*----------------------------------------------------------------------*/
  641.  
  642. void WireFrameFull(void)
  643. /* outputs the full wireframe (including elements) */
  644. {
  645.   DrawWireFull (ObjectHead);
  646. }  
  647.  
  648. /*----------------------------------------------------------------------*/
  649.  
  650. void WireFrame(void)
  651. /* outputs the coarse wireframe (only patches) */
  652. {
  653.   DrawWire (ObjectHead);
  654. }
  655.  
  656. /*----------------------------------------------------------------------*/
  657.  
  658. void Faster(void)
  659.      /* change MoveFactor so user moves faster */
  660.      /* change TurnFactor so user turns faster */
  661. {
  662.   MoveFactor = MoveFactor*1.5; /* add 50% */
  663.   TurnFactor = TurnFactor*1.5; /* ditto */
  664. }
  665.  
  666. /*----------------------------------------------------------------------*/
  667.  
  668. void Slower(void)
  669.      /* change MoveFactor so user moves slower */
  670.      /* change TurnFactor so user turns faster */
  671. {
  672.   MoveFactor = MoveFactor/1.5;
  673.   TurnFactor = TurnFactor/1.5;
  674. }
  675.   
  676. /*----------------------------------------------------------------------*/
  677. void ChangeView(int dir)
  678. /* changes the viewpoint for walkthrough */
  679. {
  680.   Matrix New;
  681.   double c,s;
  682.   Vector temp1,temp2;
  683.   Vector u1,v1,n1;
  684.   
  685.   switch (dir) {
  686.   case 1: {
  687.   VRP.x += MoveFactor*n.dx;
  688.   VRP.y += MoveFactor*n.dy;
  689.   VRP.z += MoveFactor*n.dz;
  690.   break; }
  691.   case 2: {
  692.   VRP.x -= MoveFactor*n.dx;
  693.   VRP.y -= MoveFactor*n.dy;
  694.   VRP.z -= MoveFactor*n.dz;
  695.   break; }
  696.   case 3: {
  697.     createIdentity(4,New.mat);
  698.     c = cos((-1.0)*TurnFactor*PI/180.0);
  699.     s = sin((-1.0)*TurnFactor*PI/180.0);
  700.     New.mat[0] = c;
  701.     New.mat[2] = (-1.0)*s;
  702.     New.mat[8] = s;
  703.     New.mat[10] = c;
  704.     temp1.dx = 0.0;
  705.     temp1.dy = 0.0;
  706.     temp1.dz = 1.0;
  707.     n1.dx = temp1.dx * New.mat[0] + temp1.dy * New.mat[4] + temp1.dz * New.mat[8] + 1.0 * New.mat[12];
  708.     n1.dy = temp1.dx * New.mat[1] + temp1.dy * New.mat[5] + temp1.dz * New.mat[9] + 1.0 * New.mat[13];
  709.     n1.dz = temp1.dx * New.mat[2] + temp1.dy * New.mat[6] + temp1.dz * New.mat[10] + 1.0 * New.mat[14];
  710.     temp1.dx  = u.dx*n1.dx + v.dx*n1.dy + n.dx*n1.dz + VRP.x;
  711.     temp1.dy  = u.dy*n1.dx + v.dy*n1.dy + n.dy*n1.dz + VRP.y;
  712.     temp1.dz  = u.dz*n1.dx + v.dz*n1.dy + n.dz*n1.dz + VRP.z;
  713.     temp2.dx = 1.0;
  714.     temp2.dy = 0.0;
  715.     temp2.dz = 0.0;
  716.     u1.dx = temp2.dx * New.mat[0] + temp2.dy * New.mat[4] + temp2.dz * New.mat[8] + 1.0 * New.mat[12];
  717.     u1.dy = temp2.dx * New.mat[1] + temp2.dy * New.mat[5] + temp2.dz * New.mat[9] + 1.0 * New.mat[13];
  718.     u1.dz = temp2.dx * New.mat[2] + temp2.dy * New.mat[6] + temp2.dz * New.mat[10] + 1.0 * New.mat[14];
  719.     temp2.dx  = u.dx*u1.dx + v.dx*u1.dy + n.dx*u1.dz + VRP.x;
  720.     temp2.dy  = u.dy*u1.dx + v.dy*u1.dy + n.dy*u1.dz + VRP.y;
  721.     temp2.dz  = u.dz*u1.dx + v.dz*u1.dy + n.dz*u1.dz + VRP.z;
  722.     temp1.dx -= VRP.x;
  723.     temp1.dy -= VRP.y;
  724.     temp1.dz -= VRP.z;
  725.     temp2.dx -= VRP.x;
  726.     temp2.dy -= VRP.y;
  727.     temp2.dz -= VRP.z;        
  728.     n = Normalize(temp1);
  729.     u = Normalize(temp2);
  730.     break; }
  731.   case 4: {
  732.     createIdentity(4,New.mat);
  733.     c = cos(TurnFactor*PI/180.0);
  734.     s = sin(TurnFactor*PI/180.0);
  735.     New.mat[0] = c;
  736.     New.mat[2] = (-1.0)*s;
  737.     New.mat[8] = s;
  738.     New.mat[10] = c;
  739.     temp1.dx = 0.0;
  740.     temp1.dy = 0.0;
  741.     temp1.dz = 1.0;
  742.     n1.dx = temp1.dx * New.mat[0] + temp1.dy * New.mat[4] + temp1.dz * New.mat[8] + 1.0 * New.mat[12];
  743.     n1.dy = temp1.dx * New.mat[1] + temp1.dy * New.mat[5] + temp1.dz * New.mat[9] + 1.0 * New.mat[13];
  744.     n1.dz = temp1.dx * New.mat[2] + temp1.dy * New.mat[6] + temp1.dz * New.mat[10] + 1.0 * New.mat[14];
  745.     temp1.dx  = u.dx*n1.dx + v.dx*n1.dy + n.dx*n1.dz + VRP.x;
  746.     temp1.dy  = u.dy*n1.dx + v.dy*n1.dy + n.dy*n1.dz + VRP.y;
  747.     temp1.dz  = u.dz*n1.dx + v.dz*n1.dy + n.dz*n1.dz + VRP.z;
  748.     temp2.dx = 1.0;
  749.     temp2.dy = 0.0;
  750.     temp2.dz = 0.0;
  751.     u1.dx = temp2.dx * New.mat[0] + temp2.dy * New.mat[4] + temp2.dz * New.mat[8] + 1.0 * New.mat[12];
  752.     u1.dy = temp2.dx * New.mat[1] + temp2.dy * New.mat[5] + temp2.dz * New.mat[9] + 1.0 * New.mat[13];
  753.     u1.dz = temp2.dx * New.mat[2] + temp2.dy * New.mat[6] + temp2.dz * New.mat[10] + 1.0 * New.mat[14];
  754.     temp2.dx = u.dx*u1.dx + v.dx*u1.dy + n.dx*u1.dz + VRP.x;
  755.     temp2.dy = u.dy*u1.dx + v.dy*u1.dy + n.dy*u1.dz + VRP.y;
  756.     temp2.dz = u.dz*u1.dx + v.dz*u1.dy + n.dz*u1.dz + VRP.z;
  757.     temp1.dx -= VRP.x;
  758.     temp1.dy -= VRP.y;
  759.     temp1.dz -= VRP.z;
  760.     temp2.dx -= VRP.x;
  761.     temp2.dy -= VRP.y;
  762.     temp2.dz -= VRP.z;            
  763.     n = Normalize(temp1);
  764.     u = Normalize(temp2);
  765.     break; }
  766.   case 5: {
  767.     createIdentity(4,New.mat);
  768.     c = cos((-1.0)*TurnFactor*PI/180.0);
  769.     s = sin((-1.0)*TurnFactor*PI/180.0);
  770.     New.mat[5] = c;
  771.     New.mat[6] = s;
  772.     New.mat[9] = (-1.0)*s;
  773.     New.mat[10] = c;
  774.     temp1.dx = 0.0;
  775.     temp1.dy = 0.0;
  776.     temp1.dz = 1.0;
  777.     n1.dx = temp1.dx * New.mat[0] + temp1.dy * New.mat[4] + temp1.dz * New.mat[8] + 1.0 * New.mat[12];
  778.     n1.dy = temp1.dx * New.mat[1] + temp1.dy * New.mat[5] + temp1.dz * New.mat[9] + 1.0 * New.mat[13];
  779.     n1.dz = temp1.dx * New.mat[2] + temp1.dy * New.mat[6] + temp1.dz * New.mat[10] + 1.0 * New.mat[14];
  780.     temp1.dx  = u.dx*n1.dx + v.dx*n1.dy + n.dx*n1.dz + VRP.x;
  781.     temp1.dy  = u.dy*n1.dx + v.dy*n1.dy + n.dy*n1.dz + VRP.y;
  782.     temp1.dz  = u.dz*n1.dx + v.dz*n1.dy + n.dz*n1.dz + VRP.z;
  783.     temp2.dx = 0.0;
  784.     temp2.dy = 1.0;
  785.     temp2.dz = 0.0;
  786.     v1.dx = temp2.dx * New.mat[0] + temp2.dy * New.mat[4] + temp2.dz * New.mat[8] + 1.0 * New.mat[12];
  787.     v1.dy = temp2.dx * New.mat[1] + temp2.dy * New.mat[5] + temp2.dz * New.mat[9] + 1.0 * New.mat[13];
  788.     v1.dz = temp2.dx * New.mat[2] + temp2.dy * New.mat[6] + temp2.dz * New.mat[10] + 1.0 * New.mat[14];
  789.     temp2.dx  = u.dx*v1.dx + v.dx*v1.dy + n.dx*v1.dz + VRP.x;
  790.     temp2.dy  = u.dy*v1.dx + v.dy*v1.dy + n.dy*v1.dz + VRP.y;
  791.     temp2.dz  = u.dz*v1.dx + v.dz*v1.dy + n.dz*v1.dz + VRP.z;
  792.     temp1.dx -= VRP.x;
  793.     temp1.dy -= VRP.y;
  794.     temp1.dz -= VRP.z;
  795.     temp2.dx -= VRP.x;
  796.     temp2.dy -= VRP.y;
  797.     temp2.dz -= VRP.z;            
  798.     n = temp1;
  799.     v = temp2;
  800.     break; }    
  801.   case 6: {
  802.     createIdentity(4,New.mat);
  803.     c = cos(TurnFactor*PI/180.0);
  804.     s = sin(TurnFactor*PI/180.0);
  805.     New.mat[5] = c;
  806.     New.mat[6] = s;
  807.     New.mat[9] = (-1.0)*s;
  808.     New.mat[10] = c;
  809.     temp1.dx = 0.0;
  810.     temp1.dy = 0.0;
  811.     temp1.dz = 1.0;
  812.     n1.dx = temp1.dx * New.mat[0] + temp1.dy * New.mat[4] + temp1.dz * New.mat[8] + 1.0 * New.mat[12];
  813.     n1.dy = temp1.dx * New.mat[1] + temp1.dy * New.mat[5] + temp1.dz * New.mat[9] + 1.0 * New.mat[13];
  814.     n1.dz = temp1.dx * New.mat[2] + temp1.dy * New.mat[6] + temp1.dz * New.mat[10] + 1.0 * New.mat[14];
  815.     temp1.dx  = u.dx*n1.dx + v.dx*n1.dy + n.dx*n1.dz + VRP.x;
  816.     temp1.dy  = u.dy*n1.dx + v.dy*n1.dy + n.dy*n1.dz + VRP.y;
  817.     temp1.dz  = u.dz*n1.dx + v.dz*n1.dy + n.dz*n1.dz + VRP.z;
  818.     temp2.dx = 0.0;
  819.     temp2.dy = 1.0;
  820.     temp2.dz = 0.0;
  821.     v1.dx = temp2.dx * New.mat[0] + temp2.dy * New.mat[4] + temp2.dz * New.mat[8] + 1.0 * New.mat[12];
  822.     v1.dy = temp2.dx * New.mat[1] + temp2.dy * New.mat[5] + temp2.dz * New.mat[9] + 1.0 * New.mat[13];
  823.     v1.dz = temp2.dx * New.mat[2] + temp2.dy * New.mat[6] + temp2.dz * New.mat[10] + 1.0 * New.mat[14];
  824.     temp2.dx  = u.dx*v1.dx + v.dx*v1.dy + n.dx*v1.dz + VRP.x;
  825.     temp2.dy  = u.dy*v1.dx + v.dy*v1.dy + n.dy*v1.dz + VRP.y;
  826.     temp2.dz  = u.dz*v1.dx + v.dz*v1.dy + n.dz*v1.dz + VRP.z;
  827.     temp1.dx -= VRP.x;
  828.     temp1.dy -= VRP.y;
  829.     temp1.dz -= VRP.z;
  830.     temp2.dx -= VRP.x;
  831.     temp2.dy -= VRP.y;
  832.     temp2.dz -= VRP.z;            
  833.     n = temp1;
  834.     v = temp2;
  835.     break; }  }
  836.     
  837.   ProduceTransform (VRP,u,v,n,Eye,&Composition);
  838.   CullBackFaces (ObjectHead,Eye,VRP,n); 
  839.   TransformView (ObjectHead,Composition);
  840. }
  841.  
  842. /*----------------------------------------------------------------------*/
  843. void engine (char *SceneFileName)
  844. /* renders the scene from the initial viewpoint */
  845. {
  846.    int loop;
  847.    
  848.    ReadScene(SceneFileName);
  849.    InitWire (ViewWindow,winWidth,winHeight); /* set up the wire-frame package */
  850.    ComputeDeltas (); /* precompute the delta form factors for the hemicube */
  851.    InitComp();
  852.    
  853.  
  854.    Zbuffer = (double **)(malloc(winWidth*sizeof(double *)));
  855.    for (loop = 0;loop < winWidth;loop++)
  856.       Zbuffer[loop] = (double *)(malloc(winHeight*sizeof(double)));
  857.  
  858.    ScreenMap = (Color **)(malloc(winWidth*sizeof(Color *)));
  859.    for (loop = 0;loop < winWidth;loop++)
  860.       ScreenMap[loop] = (Color *)(malloc(winHeight*sizeof(Color)));
  861.  
  862.    renderit();
  863.    
  864.  
  865. }
  866.  
  867.  
  868. /*----------------------------------------------------------------------*/
  869.  
  870.  
  871.  
  872.  
  873.  
  874.